﻿using System.Collections.Generic;
using System.Web.UI;

namespace JQueryControlToolkit
{
    public class JQueryPage : System.Web.UI.Page
    {
        public JQuery JQuery(string selector)
        {
            return new JQueryControlToolkit.JQuery(selector);
        }

        public new JQueryPage Page
        {
            get
            {
                return this;
            }
        }

        public void Add(JQuery jquery)
        {
            JQueryPageExtensions.Add(this, jquery);
        }
    }

    public class JQueryUserControl : System.Web.UI.UserControl
    {
        public JQuery JQuery(string selector)
        {
            return new JQueryControlToolkit.JQuery(selector);
        }

        public void Add(JQuery jquery)
        {
            JQueryPageExtensions.Add(this, jquery);
        }
    }

    /// <summary>
    /// Convenience extensions for adding JQuery expression to Page. Implemented as extension methods to 
    /// minimize dependence on JQueryPage.
    /// </summary>
    public static class JQueryPageExtensions
    {
        public static List<JQuery> GetJQueries(Page page)
        {
            string jqKey = "JQueryPage.JQueries";
            List<JQuery> jQueries;

            if (page.Items[jqKey] == null)
            {
                jQueries = new List<JQuery>();
                page.Items[jqKey] = jQueries;
            }
            else
            {
                jQueries = page.Items[jqKey] as List<JQuery>;
            }

            return jQueries;
        }

        public static void Add(Page page, JQuery jquery, bool executeWhenDocumentReady)
        {
            string jqID = AddToPageItems(page, jquery);
            string outputScript;
            if (executeWhenDocumentReady)
                outputScript = Extensions.ToDocumentReady(Extensions.ToFunctionExpression(jquery)).ToScript();
            else
                outputScript = jquery.ToScript();
            page.ClientScript.RegisterStartupScript(page.GetType(), jqID, outputScript, true);
        }

        public static void Add(Page page, JQuery jquery)
        {
            Add(page, jquery, true);
        }

        public static void Add(Control control, JQuery jquery)
        {
            Add(control.Page, jquery, true);
        }

        /// <summary>
        /// Adds the JQuery object to page items.
        /// </summary>
        /// <param name="page">The page.</param>
        /// <param name="jquery">The jquery object.</param>
        /// <returns>the jQuery ID to be used for script</returns>
        private static string AddToPageItems(Page page, JQuery jquery)
        {
            string jqID = "JQuery";
            lock (GetJQueries(page))
            {
                if (!GetJQueries(page).Contains(jquery))
                {
                    GetJQueries(page).Add(jquery);
                    jqID += GetJQueries(page).Count.ToString();
                }
                else
                    jqID += GetJQueries(page).IndexOf(jquery);
            }
            return jqID;
        }

        /// <summary>
        /// Adds the JQuery object to page items.
        /// </summary>
        /// <param name="page">The page.</param>
        /// <param name="jquery">The jquery object.</param>
        /// <returns>the DomResult ID to be used for script</returns>
        private static string AddToPageItems(Page page, DomResult js)
        {
            return js.GetHashCode().ToString();
        }

        public static void AddAjaxLoad(Page page, DomResult js, bool executeWhenPageReady)
        {
            string jsID = AddToPageItems(page, js);
            string outputScript = js.ToScript();
            if (executeWhenPageReady)
                outputScript = Extensions.ToAjaxPageLoad(Extensions.ToFunctionExpression(outputScript));
            ScriptManager.RegisterStartupScript(page, page.GetType(), jsID, outputScript, true);
        }

        public static void AddAjaxLoad(Page page, JQuery jquery, bool executeWhenPageReady)
        {
            AddAjaxLoad(page, (DomResult)jquery, executeWhenPageReady);
        }

        public static void AddAjaxLoad(Page page, JQuery jquery)
        {
            AddAjaxLoad(page, jquery, true);
        }
    }
}